import type { Router } from 'vue-router'
import { useUserStoreWithOut } from '@/stores/modules/user'
import { usePermissionStoreWithOut } from '@/stores/modules/permission'
import { RootRoute, PageNotFoundRoute } from '@/router/routes'
const whiteList = ['/login']

function handleLoginRedirect(next: any, to: any, isSessionTimeout: boolean) {
  if (!isSessionTimeout) {
    next((to.query?.redirect as string) || '/')
    return true
  }
  return false
}

function handleNoToken(to: any, next: any) {
  if (to.meta.ignoreAuth) {
    next()
    return true
  }
  const redirectData: { path: string; replace: boolean; query?: Recordable<string> } = {
    path: '/login',
    replace: true,
    query: { redirect: to.path }
  }
  next(redirectData)
  return true
}

export function createPermissionGuard(router: Router) {
  const userStore = useUserStoreWithOut()
  const permissionStore = usePermissionStoreWithOut()

  router.beforeEach(async (to, from, next) => {
    const homePath = userStore.getUserInfo.homePath || '/home'
    const token = userStore.getToken

    if (whiteList.includes(to.path)) {
      if (to.path === '/login' && token) {
        const isSessionTimeout = userStore.getSessionTimeout
        const handled = handleLoginRedirect(next, to, isSessionTimeout)
        if (handled) return
      }
      next()
      return
    }

    if (!token) {
      const handled = handleNoToken(to, next)
      if (handled) return
    }

    if (from.path === RootRoute.path && to.path === '/home' && homePath !== '/home') {
      next(homePath)
      return
    }

    if (from.path === '/login' && to.name === PageNotFoundRoute.name && to.fullPath !== homePath) {
      next(homePath)
      return
    }

    if (userStore.getLastUpdateTime === 0) {
      try {
        await userStore.getUserInfoAction()
      } catch {
        next()
        return
      }
    }

    const isLoaded = permissionStore.getRouterLoad
    if (!isLoaded) {
      try {
        const routers = await permissionStore.buildRoutesAction()
        routers.forEach(route => {
          router.addRoute(route as any)
        })
        next({ ...to, replace: true })
        return
      } catch (e) {
        next({ path: '/error', replace: true })
        return
      }
    }

    if (to.name === PageNotFoundRoute.name) {
      next({ path: to.fullPath, replace: true, query: to.query })
    } else {
      next()
    }
  })
}
